package com.cskaoyan.javase.oop3._0abstract._1basic;

import java.nio.channels.Pipe;

/**
 * 抽象类的特点:
 * 1. 类名命名特点
 * 2. 能用哪些修饰符？
 * 3. 成员特点
 *    1. 普通成员
 *    2. 静态成员
 *    3. 抽象方法
 * 4. 构造器
 * 5. 代码块
 *
 * 1.抽象类的命名特点: 抽象类仍然是一个class,所以遵循大驼峰的命名规范,而且因为它比较特殊,为了体现特殊性,也让别的开发者
 *      能够一眼知道这个类是抽象类,抽象类的命名,一般会以Abstract或Base开头,比如AbstractPerson BasePerson
 * 2.访问权限修饰,只有public和缺省,默认权限.注意它不能和final关键字写在一起.它们冲突
 * 3.成员特点:
 *      可以定义普通类都有的成员(包括普通成员和静态成员)
 *      抽象类可以允许没有抽象方法吗? 可以
 *      但是抽象类没有抽象方法 是没有意义的
 *      抽象类就是为了定义抽象方法而存在的
 *
 *      抽象方法:
 *      [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 *      抽象方法在继承中起到"占位"的作用,一个普通子类一旦继承抽象方法,必须实现抽象方法
 *      同样抽象类中的普通方法,可以起到作为子类默认实现的作用,子类可以选择直接继承使用,也可以选择继承重写,选择的权力在子类手里
 *
 *      思考: 抽象方法的声明中,和哪些关键字是冲突的?不能混用的?
 *      1.private,私有方法不能被重写
 *      2.final,final方法不能被重写
 *      3.static,静态方法不能被重写.父子类同名是两个独立的方法
 *      4.构造方法,显然不能是抽象的.
 *
 * 思考: 抽象类有没有构造器/构造方法?
 * 有，虽然不能自己用，但是给子类对象初始化时可以使用
 *
 * 一句话: 在Java中,任何类都有构造器(正确的)
 *
 * 综上所述: 抽象类可以有普通类拥有的所有结构,包括成员,构造器,代码块等.只不过多了一个抽象方法
 *
 * 立刻推出: 我们不考虑创建对象的情况下,直接把一个类声明为抽象,可以吗? 是可以的,普通类拥有的成员它都有
 * 一个抽象类能不能直接继承一个普通类呢?
 * 当然可以,因为就算不写,它也直接继承Object
 *
 * 抽象类的子类特点:
 *      1.普通类,必须实现所有抽象方法,这是强制的
 *      2.抽象类,完全可以不实现任何抽象方法,当然也可以选择去实现,这是你的自由
 *
 *
 * @since 09:58
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student(10, 20, "张三");
        System.out.println(s.a);
    }
}

// Illegal combination of modifiers: 'final' and 'abstract'
abstract class AbstractPerson {
    // 定义成员
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    {
        // 构造代码块
    }

    static {
        // 静态代码块
    }

    public void test() {
        System.out.println("Abstract Person");
    }

    public static void testStatic() {
    }

    // 定义抽象方法
    public abstract void testAbstract();
    public abstract void testAbstract2();


    // 构造器


    public AbstractPerson() {
    }

    public AbstractPerson(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

// Class 'Student' must either be declared abstract or implement abstract method 'testAbstract()' in 'AbstractPerson'
class Student extends AbstractPerson {
    String name;

    // 实现父类抽象方法的过程就是方法的重写
    // 建议直接alt+回车 报错 直接重写方法
    @Override
    public void testAbstract() {
        System.out.println("我是Student!");
    }

    @Override
    public void testAbstract2() {
        System.out.println("我是Student2!");
    }

    public Student() {
        // super();
    }

    public Student(int a, int b, String name) {
        super(a, b);
        this.name = name;
    }
}
abstract class Teacher extends AbstractPerson{
    @Override
    public void testAbstract() {
        System.out.println("teacher");
    }
}